/**
 * EventEmitter
 * 1. on emit 订阅 发送
 * 2. on 支持链式调用
 * 3. off 删除事件 支持链式调用
 * 4. once 触发一次
 */
class EventEmitter {
  _events = {}; // {[key: string]: fn[]}
  constructor() {}
  bind(eventName, listener, once = false) {
    if(!eventName || !listener) {
      return;
    }
    if(!this._events[eventName]) {
      this._events[eventName] = [];
    }
    const index = this._events[eventName].findIndex(listenerFn => listenerFn == listener);
    if(index >= 0) {
      return;
    }
    this._events[eventName].push(once ? {once: true, listener} : listener);
    return this;
  }
  on(eventName, listener) {
    return this.bind(eventName, listener);
  }
  once(eventName, listener) {
    return this.bind(eventName, listener, true)
  }

  emit(eventName, args) {
    if(this._events[eventName] && this._events[eventName].length > 0) {
      this._events[eventName].forEach(listener => {
        if(listener.once) {
          listener.listener.call(null, args);
          this.off(eventName, listener.listener)
        } else {
          listener.call(null, args);
        }
      })
    }
  }

  off(eventName, listener) {
    let eventListeners = this._events[eventName];
    if(eventListeners && eventListeners.length > 0) {
      if (!listener) {
        eventListeners = [];
      }
      const index = eventListeners.findIndex(listenerFn => {
        if(listenerFn.once) {
          return listenerFn.listener == listener;
        } else {
          return listenerFn == listener;
        }
      });
      if(index >= 0) {
        eventListeners.splice(index, 1);
      }
    }
    return this;
  }
}